#pragma once
#include <iostream>
#include <string>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <functional>
#include "Socket.hpp"
#include "Log.hpp"
#include "INetAddr.hpp"

using namespace socket_ns;

class TcpServer;

using http_t = std::function<std::string(std::string)>;


struct ThreadData
{
    socket_sptr socket;
    INetAddr addr;
    TcpServer *uq;
    ThreadData(socket_sptr sock, INetAddr address, TcpServer *usvr)
        : socket(sock), addr(address), uq(usvr)
    {
    }
};

class TcpServer
{
public:
    TcpServer(uint16_t port, http_t func)   
        :_addr("0", port)
        ,_listenSock(std::make_unique<TcpSocket>())
        ,_isrunning(false)
        ,_http_service(func)
    {
        _listenSock->BuildListenServer(_addr);
    }


    static void *HandlerTask(void *args)
    {
        pthread_detach(pthread_self());
        ThreadData *td = static_cast<ThreadData *>(args);

        std::string request;
        int n = td->socket->Recv(request);
        if(n > 0)
        {
            //LOG(DEBUG, "get a request : %s\n", request.c_str());
            std::string response = td->uq->_http_service(request);
            td->socket->Send(response);
        }
        
        td->socket->Close();
        delete td;
        return nullptr;
    }

    void Loop()
    {
        _isrunning = true;
        while (true)
        {
            INetAddr peer;
            socket_sptr sptr = _listenSock->Acceptor(peer);

            // Version 2 多线程
            pthread_t tid;
            ThreadData *td = new ThreadData(sptr, INetAddr(peer), this);
            pthread_create(&tid, nullptr, HandlerTask, td); // 将线程进行分离
        }
    }
    ~TcpServer()
    {
    }

private:
    INetAddr _addr;
    std::unique_ptr<Socket> _listenSock;
    bool _isrunning;
    http_t _http_service;
};